package com.example.a086.httpdemo.http;

import android.content.Context;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;

import com.example.a086.httpdemo.http.base.EngineCallback;
import com.example.a086.httpdemo.http.base.HttpUtils;
import com.example.a086.httpdemo.http.base.IHttpEngine;
import com.example.a086.httpdemo.http.base.ThreadPoolUtil;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;


/**
 * Created by 086 on 2018/5/8.
 */

public class HttpClientEngine implements IHttpEngine {
    private final int CONNECT_TIME_OUT = 10000;
    private final int READ_TIME_OUT = 20000;
    private Handler mHandler = new Handler();

    @Override
    public void get(Context context, final String url, final Map<String, Object> map, final EngineCallback callback) {
        ThreadPoolUtil.execute(new Runnable() {
            @Override
            public void run() {
                getRequest(url, map, callback);
            }
        });

    }


    @Override
    public void post(Context context, final String url, final String body, final EngineCallback callback) {
        ThreadPoolUtil.execute(new Runnable() {
            @Override
            public void run() {
                postRequest(url, body, callback);
            }
        });

    }

    @Override
    public void uploadFile(final String url, final Map<String, Object> params, final Map<String, File> files, final EngineCallback callback) {
        ThreadPoolUtil.execute(new Runnable() {
            @Override
            public void run() {
                uploadFiles(url, params, files, callback);
            }
        });
    }


    private void getRequest(String url, Map<String, Object> map, final EngineCallback callback) {
        String path = HttpUtils.jointParams(url, map);
        try {
            //打开连接
            URL uRL = new URL(path.trim());
            final HttpURLConnection urlConnection = (HttpURLConnection) uRL.openConnection();
            urlConnection.setConnectTimeout(CONNECT_TIME_OUT);
            urlConnection.setReadTimeout(READ_TIME_OUT);
            urlConnection.setRequestProperty("Content-Type", "application/json");
            urlConnection.setRequestProperty("Accept", "application/json");

            if (200 == urlConnection.getResponseCode()) {
                //得到输入流
                InputStream is = urlConnection.getInputStream();
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int len = 0;
                while (-1 != (len = is.read(buffer))) {
                    baos.write(buffer, 0, len);
                    baos.flush();
                }
                is.close();
                baos.close();
                final String json = baos.toString("utf-8");
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onSuccess(json);
                    }
                });

            } else {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            callback.onFailed(urlConnection.getResponseMessage());
                        } catch (IOException e) {
                            e.printStackTrace();
                            callback.onFailed(e.getMessage());
                        }
                    }
                });
            }
        } catch (final IOException e) {
            e.printStackTrace();
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    callback.onFailed(e.getMessage());
                }
            });
        }
    }

    private void postRequest(String url, String body, final EngineCallback callback) {
        URL uRL = null;
        PrintWriter printWriter = null;
        try {
            uRL = new URL(url);
            final HttpURLConnection httpURLConnection = (HttpURLConnection) uRL.openConnection();
            httpURLConnection.setRequestMethod("POST");// 提交模式
            httpURLConnection.setConnectTimeout(CONNECT_TIME_OUT);//连接超时 单位毫秒
            httpURLConnection.setReadTimeout(READ_TIME_OUT);//读取超时 单位毫秒
            httpURLConnection.setUseCaches(false);

            httpURLConnection.setRequestProperty("Content-Type", "application/json");
            httpURLConnection.setRequestProperty("Accept", "application/json");
            httpURLConnection.setRequestProperty("Charset", "UTF-8");
            httpURLConnection.setRequestProperty("X-ClientType", "2");//发送自定义的头信息
            httpURLConnection.setRequestProperty("Connection", "Keep-Alive");
            // 发送POST请求必须设置如下两行
            httpURLConnection.setDoOutput(true);
            httpURLConnection.setDoInput(true);

            // 获取URLConnection对象对应的输出流
            printWriter = new PrintWriter(httpURLConnection.getOutputStream());
            // 发送请求参数
            printWriter.write(body);
            // flush输出流的缓冲
            printWriter.flush();
            if (200 == httpURLConnection.getResponseCode()) {
                //开始获取数据
                BufferedInputStream bis = new BufferedInputStream(httpURLConnection.getInputStream());
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                int len;
                byte[] arr = new byte[1024];
                while ((len = bis.read(arr)) != -1) {
                    bos.write(arr, 0, len);
                    bos.flush();
                }
                bis.close();
                bos.close();
                final String json = bos.toString("utf-8");
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onSuccess(json);
                    }
                });

            } else {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            callback.onFailed(httpURLConnection.getResponseMessage());
                        } catch (IOException e) {
                            e.printStackTrace();
                            callback.onFailed(e.getMessage());
                        }
                    }
                });

            }
        } catch (final Exception e) {
            e.printStackTrace();
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    callback.onFailed(e.getMessage());
                }
            });

        } finally {
            if (printWriter != null) {
                printWriter.close();
            }

        }
    }

    private void uploadFiles(String actionUrl,
                             Map<String, Object> params,
                             Map<String, File> files, EngineCallback callback) {

        String BOUNDARY = java.util.UUID.randomUUID().toString();
        String PREFIX = "--", LINEND = "\r\n";
        String MULTIPART_FROM_DATA = "multipart/form-data";
        String CHARSET = "UTF-8";

        URL uri = null;
        try {
            uri = new URL(actionUrl);
            HttpURLConnection conn = (HttpURLConnection) uri.openConnection();
            conn.setReadTimeout(30 * 1000); // 缓存的最长时间
            conn.setDoInput(true);// 允许输入
            conn.setDoOutput(true);// 允许输出
            conn.setUseCaches(false); // 不允许使用缓存
            conn.setRequestMethod("POST");
            conn.setRequestProperty("connection", "keep-alive");
            conn.setRequestProperty("Charsert", "UTF-8");
            conn.setRequestProperty("Content-Type", MULTIPART_FROM_DATA
                    + ";boundary=" + BOUNDARY);
            StringBuilder sb = new StringBuilder();

            if (params != null) {
                // 首先组拼文本类型的参数
                for (Map.Entry<String, Object> entry : params.entrySet()) {
                    sb.append(PREFIX);
                    sb.append(BOUNDARY);
                    sb.append(LINEND);
                    sb.append("Content-Disposition: form-data; name=\""
                            + entry.getKey() + "\"" + LINEND);
                    sb.append("Content-Type: text/plain; charset=" + CHARSET + LINEND);
                    sb.append("Content-Transfer-Encoding: 8bit" + LINEND);
                    sb.append(LINEND);
                    sb.append(entry.getValue());
                    sb.append(LINEND);
                }

            }

            DataOutputStream outStream = new DataOutputStream(
                    conn.getOutputStream());
            if (!TextUtils.isEmpty(sb.toString())) {
                outStream.write(sb.toString().getBytes());
            }


            // 发送文件数据
            if (files != null)
                for (Map.Entry<String, File> file : files.entrySet()) {
                    StringBuilder sb1 = new StringBuilder();
                    sb1.append(PREFIX);
                    sb1.append(BOUNDARY);
                    sb1.append(LINEND);
                    sb1.append("Content-Disposition: form-data; name=\"file\"; filename=\""
                            + file.getKey() + "\"" + LINEND);
                    sb1.append("Content-Type: application/octet-stream; charset="
                            + CHARSET + LINEND);
                    sb1.append(LINEND);
                    outStream.write(sb1.toString().getBytes());

                    InputStream is = new FileInputStream(file.getValue());
                    byte[] buffer = new byte[1024];
                    int len = 0;
                    while ((len = is.read(buffer)) != -1) {
                        outStream.write(buffer, 0, len);
                    }

                    is.close();
                    outStream.write(LINEND.getBytes());
                }

            // 请求结束标志
            byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINEND).getBytes();
            outStream.write(end_data);
            outStream.flush();

            // 得到响应码
            int res = conn.getResponseCode();
            InputStream in = conn.getInputStream();
            if (res == 200) {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
                StringBuffer buffer = new StringBuffer();
                String line = "";
                while ((line = bufferedReader.readLine()) != null) {
                    buffer.append(line);
                }

                callback.onSuccess(buffer.toString());
            } else {
                callback.onFailed(conn.getResponseMessage());
            }
            outStream.close();
            conn.disconnect();

        } catch (Exception e) {
            e.printStackTrace();
            callback.onFailed(e.getMessage());
        }
    }
}
